// sphereGeometry.ts  
import PipelineObject from '../interface/pipelineObject';
import Geometry from './geometry';
import {vec3} from 'gl-matrix';

const scrtchVec3 = vec3.create();

export default class SphereGeometry extends Geometry {
    constructor(radius: number, widthSegments: number, heightSegments: number, pipeline: PipelineObject) {
        super(new Float32Array(), new Uint16Array([]), 0, 0, pipeline);

        this.setSphereData(radius, widthSegments, heightSegments);
    }

    private setSphereData(radius: number, widthSegments: number, heightSegments: number) {
        const vertices: number[] = [];
        const indices: number[] = [];

        for (let i = 0; i <= heightSegments; i++) {
            const v = i / heightSegments;
            const theta = v * Math.PI;

            for (let j = 0; j <= widthSegments; j++) {
                const u = j / widthSegments;
                const phi = u * 2 * Math.PI;

                const x = radius * Math.sin(theta) * Math.cos(phi);
                const y = radius * Math.cos(theta);
                const z = radius * Math.sin(theta) * Math.sin(phi);

                const nx = x / radius;
                const ny = y / radius;
                const nz = z / radius;

                const uCoord = u;
                const vCoord = 1 - v;

                vec3.normalize(scrtchVec3, [nx, ny, nz]);
                vec3.scale(scrtchVec3, scrtchVec3, 1);

                vertices.push(x, y, z, scrtchVec3[0], scrtchVec3[1], scrtchVec3[2], uCoord, vCoord);
            }
        }

        for (let i = 0; i < heightSegments; i++) {
            for (let j = 0; j < widthSegments; j++) {
                const first = (i * (widthSegments + 1)) + j;
                const second = first + widthSegments + 1;

                indices.push(first, first + 1, second);
                indices.push(second, first + 1, second + 1);
            }
        }

        this.setVertexData(new Float32Array(vertices));
        this.setIndexData(new Uint16Array(indices));
    }
}